﻿using System;
using System.Linq;
using GeneticAlgorithms.Alphabets;
using GeneticAlgorithms.Genomes;
using GeneticAlgorithms.Operators.Crossover;
using GeneticAlgorithms.Tests.Utils;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace GeneticAlgorithms.Tests.Operators.Crossover
{   
    /// <summary>
    ///This is a test class for BaseCrossoverOperatorTest and is intended
    ///to contain all BaseCrossoverOperatorTest Unit Tests
    ///</summary>
    public class CrossoverOperatorTestHelper<TGenome, TGene>
        where TGenome : IGenome<TGene>
    {
        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        protected void TestCross(
            IGeneticCrossover<TGenome, TGene> target,
            TGenome[] parents, 
            TGenome[] expectedChildren)
        {
            TGenome[] actualChildren = new TGenome[target.Cardinality];
            target.Cross(parents, actualChildren);
            ExtraAssert.GenomeCollectionsMatch<TGenome, TGene>(expectedChildren, actualChildren);
        }

        public ArrayGenome<bool> GetBoolGenome(int length)
        {
            return GetBoolGenome(length, true);
        }

        public ArrayGenome<bool> GetBoolGenome(int length, bool geneValue)
        {
            ArrayGenome<bool> result = new ArrayGenome<bool>(new BinaryAlphabet(), length);
            result.SetValues(geneValue);
            return result;
        }

        public ArrayGenome<bool> GetBoolGenome(int length, Func<int, bool> getValue)
        {
            ArrayGenome<bool> result = new ArrayGenome<bool>(new BinaryAlphabet(), length);
            result.SetValues(getValue);
            return result;
        }

        public ArrayGenome<int> GetIntGenome(int length)
        {
            return GetIntGenome(length, i => i);
        }

        public ArrayGenome<int> GetIntGenome(int length, Func<int, int> getValue)
        {
            ArrayGenome<int> result = new ArrayGenome<int>(new IntAlphabet(), length);
            result.SetValues(getValue);
            return result;
        }
    }
}
